package com.itaming.lycheeframework.security.authentication;

import com.itaming.lycheeframework.support.utils.CollectionUtil;
import com.itaming.lycheeframework.support.utils.NullSafeUtil;

import java.util.Collection;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;

/**
 * 认证上下文持有者
 *
 * @author A.Ming
 */
public class AuthContextHolder {

    /**
     * 当前线程认证上下文
     */
    private static final ThreadLocal<AuthContext<?, ?>> context = new ThreadLocal<>();

    /**
     * 设置认证上下文
     *
     * @param authContext
     */
    static void setContext(AuthContext<?, ?> authContext) {
        context.set(authContext);
    }

    /**
     * 清理
     */
    static void clear() {
        context.remove();
    }

    /**
     * 获取认证用户信息
     *
     * @return 用户信息
     */
    @SuppressWarnings("unchecked")
    public static <E> E getUser() {
        return (E) getContextOpt().map(AuthContext::getUser).orElse(null);
    }

    /**
     * 获取认证用户信息属性
     *
     * @param lambda 属性获取函数
     * @return 用户信息属性值
     */
    public static <E, F> F get(Function<E, F> lambda) {
        E user = getUser();
        return user != null ? lambda.apply(user) : null;
    }

    /**
     * 是否具有指定的权限
     *
     * @param permission 权限
     * @return boolean
     */
    public static boolean hasPermission(String permission) {
        return CollectionUtil.contains(getPermissions(), permission);
    }

    /**
     * 是否具有指定的全部权限
     *
     * @param permissions 权限集合
     * @return boolean
     */
    public static boolean hasAllPermission(String... permissions) {
        return hasAllPermission(NullSafeUtil.asList(permissions));
    }

    /**
     * 是否具有指定的全部权限
     *
     * @param permissions 权限集合
     * @return boolean
     */
    public static boolean hasAllPermission(Collection<String> permissions) {
        return CollectionUtil.containsAll(getPermissions(), permissions);
    }

    /**
     * 是否具有任意一个指定的权限
     *
     * @param permissions 权限集合
     * @return boolean
     */
    public static boolean hasAnyPermission(String... permissions) {
        return hasAnyPermission(NullSafeUtil.asList(permissions));
    }

    /**
     * 是否具有任意一个指定的权限
     *
     * @param permissions 权限集合
     * @return boolean
     */
    public static boolean hasAnyPermission(Collection<String> permissions) {
        return CollectionUtil.containsAny(getPermissions(), permissions);
    }

    /**
     * 是否具有指定的角色
     *
     * @param role 角色
     * @return boolean
     */
    public static boolean hasRole(String role) {
        return CollectionUtil.contains(getRoles(), role);
    }

    /**
     * 是否具有指定的全部角色
     *
     * @param roles 角色集合
     * @return boolean
     */
    public static boolean hasAllRole(String... roles) {
        return hasAllRole(NullSafeUtil.asList(roles));
    }

    /**
     * 是否具有指定的全部角色
     *
     * @param roles 角色集合
     * @return boolean
     */
    public static boolean hasAllRole(Collection<String> roles) {
        return CollectionUtil.containsAll(getRoles(), roles);
    }

    /**
     * 是否具有任意一个指定的角色
     *
     * @param roles 角色集合
     * @return boolean
     */
    public static boolean hasAnyRole(String... roles) {
        return hasAnyPermission(NullSafeUtil.asList(roles));
    }

    /**
     * 是否具有任意一个指定的角色
     *
     * @param roles 角色集合
     * @return boolean
     */
    public static boolean hasAnyRole(Collection<String> roles) {
        return CollectionUtil.containsAll(getRoles(), roles);
    }

    /**
     * 是否为管理员
     *
     * @return boolean
     */
    public static boolean isAdmin() {
        return getContextOpt().map(AuthContext::isAdmin).orElse(false);
    }

    /**
     * 是否为超级管理员
     *
     * @return boolean
     */
    public static boolean isSuperAdmin() {
        return getContextOpt().map(AuthContext::isSuperAdmin).orElse(false);
    }

    /**
     * 获取权限集合
     *
     * @return 权限集合
     */
    private static Set<String> getPermissions() {
        return getContextOpt().map(AuthContext::getPermissions).orElse(null);
    }

    /**
     * 获取角色集合
     *
     * @return 角色集合
     */
    private static Set<String> getRoles() {
        return getContextOpt().map(AuthContext::getRoles).orElse(null);
    }

    /**
     * 获取上下文
     *
     * @return 上下文
     */
    private static Optional<AuthContext<?, ?>> getContextOpt() {
        return Optional.ofNullable(context.get());
    }

}
